package cn.anecansaitin.firecrafting.common.menu;

import cn.anecansaitin.firecrafting.common.block.entity.FireInterfaceEntity;
import com.google.common.collect.ImmutableList;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.SlotItemHandler;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class FireInterfaceMenu extends AbstractContainerMenu {
    private final FireInterfaceEntity blockEntity;
    private final ImmutableList<Slot> ingredientSlots;
    private final ImmutableList<Slot> filterSlots;
    private boolean filter = false;

    public FireInterfaceMenu(int id, Inventory playerInv, FriendlyByteBuf buf) {
        this(id, playerInv, buf.readBlockPos());
    }

    public FireInterfaceMenu(int id, Inventory playerInv, BlockPos pos) {
        super(ModMenuTypes.FIRE_INTERFACE_MENU.get(), id);
        blockEntity = (FireInterfaceEntity) playerInv.player.level.getBlockEntity(pos);
        ImmutableList<Slot> playerSlots = buildPlayerInvSlot(playerInv);
        ingredientSlots = buildIngredientSlots();
        ImmutableList<Slot> productSlots = buildProductSlots();
        filterSlots = buildFilterSlot();
        addSlots(playerSlots);
        addSlots(ingredientSlots);
        addSlots(productSlots);
    }

    //判断玩家是否能打开gui
    @Override
    public boolean stillValid(@NotNull Player player) {
        return blockEntity.getLevel() == player.getLevel() && player.position().distanceTo(Vec3.atCenterOf(blockEntity.getBlockPos()).add(0.5, 0.5, 0.5)) < 6;
    }

    //该方法本身不用于服务端调用，因默认返回false，参数满足需求且无特殊用途，因此被用来处理客户端通过网络发来的请求
    //在原版中，该方法被用于附魔台点击事件的客户端调用
    @Override
    public boolean clickMenuButton(@NotNull Player player, int id) {
        if (id == 0) {
            filter = !filter;
            if (filter) {
                for (int i = 0, filterSlotsSize = filterSlots.size(); i < filterSlotsSize; i++) {
                    Slot slot = filterSlots.get(i);
                    slots.set(36 + i, slot);
                }
            } else {
                for (int i = 0, ingredientSlotsSize = ingredientSlots.size(); i < ingredientSlotsSize; i++) {
                    Slot slot = ingredientSlots.get(i);
                    slots.set(36 + i, slot);
                }
            }
        }
        return false;
    }

    private ImmutableList<Slot> buildPlayerInvSlot(Inventory playerInv) {
        ImmutableList.Builder<Slot> builder = ImmutableList.builder();
        //创建玩家背包
        for (int row = 0; row < 3; row++) {
            for (int column = 0; column < 9; column++) {
                builder.add(new Slot(playerInv, column + row * 9 + 9, 8 + column * 18, 111 + row * 18));
            }
        }
        //创建工具栏
        for (int col = 0; col < 9; ++col) {
            builder.add(new Slot(playerInv, col, 8 + col * 18, 169));
        }

        return builder.build();
    }

    private ImmutableList<Slot> buildIngredientSlots() {
        ImmutableList.Builder<Slot> builder = ImmutableList.builder();
        //原料栏
        for (int row = 0; row < 2; row++) {
            for (int column = 0; column < 9; column++) {
                builder.add(new SlotItemHandler(blockEntity.getItemIn(), column + row * 9, 8 + column * 18, 18 + row * 27));
            }
        }

        return builder.build();
    }

    private ImmutableList<Slot> buildProductSlots() {
        ImmutableList.Builder<Slot> builder = ImmutableList.builder();
        //产物栏
        for (int col = 0; col < 9; ++col) {
            builder.add(new SlotItemHandler(blockEntity.getItemOut(), col, 8 + col * 18, 81) {
                @Override
                public boolean mayPlace(@NotNull ItemStack stack) {
                    return false;
                }
            });
        }

        return builder.build();
    }

    private ImmutableList<Slot> buildFilterSlot() {
        ImmutableList.Builder<Slot> builder = ImmutableList.builder();
        int index = 36;
        //创建过滤栏
        for (int row = 0; row < 2; row++) {
            for (int column = 0; column < 9; column++) {
                SlotItemHandler slot = new SlotItemHandler(blockEntity.getFilter(), column + row * 9, 8 + column * 18, 18 + row * 27) {
                    @Override
                    public @NotNull ItemStack safeInsert(@NotNull ItemStack stack, int count) {
                        set(stack.copy().split(1));
                        return stack;
                    }
                };
                ((Slot)slot).index = index++;
                builder.add(slot);
            }
        }

        return builder.build();
    }

    private void addSlots(List<Slot> slots) {
        for (Slot slot : slots) {
            addSlot(slot);
        }
    }

    @Override
    public void clicked(int slotId, int dragType, @NotNull ClickType clickType, @NotNull Player player) {
        Slot slot = slotId < 0 ? null : getSlot(slotId);

        if (!filter || slot == null || slotId >= 54 || slotId <= 35) {
            super.clicked(slotId, dragType, clickType, player);
            return;
        }

        ItemStack copyStack = getCarried().copy();
        copyStack.setCount(1);

        slot.set(copyStack);
    }

    //处理物品的快速移动
    @Override
    public @NotNull ItemStack quickMoveStack(@NotNull Player player, int slotIn) {
        ItemStack stack;
        Slot slot = slots.get(slotIn);

        if (!slot.hasItem()) {
            return ItemStack.EMPTY;
        }

        ItemStack itemStack = slot.getItem();
        stack = itemStack.copy();
        int invStart = 0;
        int invEnd = invStart + 27;
        int hotEnd = invEnd + 9;
        int inEnd = hotEnd + blockEntity.getItemIn().getSlots();

        if (slotIn < hotEnd && !filter) {
            if (!moveItemStackTo(itemStack, hotEnd, inEnd, false)) {
                return ItemStack.EMPTY;
            }
        } else if (filter && slotIn < inEnd){
            return ItemStack.EMPTY;
        } else if (!moveItemStackTo(itemStack, invEnd, hotEnd, false) && !moveItemStackTo(itemStack, invStart, invEnd, false)) {
            return ItemStack.EMPTY;
        }


        if (itemStack.isEmpty()) {
            slot.set(ItemStack.EMPTY);
        } else {
            slot.setChanged();
        }

        if (itemStack.getCount() == stack.getCount()) {
            return ItemStack.EMPTY;
        }

        slot.onTake(player, itemStack);

        return stack;
    }

    public FireInterfaceEntity getBlockEntity() {
        return blockEntity;
    }

    public boolean isFilter() {
        return filter;
    }
}
